use sqlite_wasm_rs::sqlite3_stmt;
use crate::db::dao::base_dao::Adder;
use crate::db::db::{Db, DbParamType};
use crate::db::pojo::pojo::{ImFeedback};
use crate::db::util::{db_get_enum, db_get_int64, db_get_string, db_get_time};

const SELECT_COLUMNS: &'static str = "id, currentUserId, serverId, title, content, result, status statusValue, createTime, updateTime";

pub fn feedback_inserts(db: Db, feedbacks: &mut Vec<&mut ImFeedback>) {
    if feedbacks.is_empty() {
        return;
    }

    let sql = c"insert into im_feedback(currentUserId, serverId, title, content, result, status, createTime, updateTime) values(?, ?, ?, ?, ?, ?, ?, ?)";

    let mut params = vec![];
    for feedback in feedbacks.iter() {
        let mut param = vec![];
        param.push(DbParamType::Str(&*feedback.user_id));
        param.push(DbParamType::OptionStr(feedback.server_id.as_ref()));
        param.push(DbParamType::Str(&*feedback.title));
        param.push(DbParamType::Str(&*feedback.content));
        param.push(DbParamType::OptionStr(feedback.result.as_ref()));
        param.push(DbParamType::Byte(feedback.status.clone() as i8));
        param.push(DbParamType::DateTime2(&feedback.create_time));
        param.push(DbParamType::DateTime2(&feedback.update_time));
        params.push(param);
    }

    log::info!("db feedback params {:?}", params);
    let ids = db.inserts("feedback insert", sql, params);
    assert_eq!(ids.len(), feedbacks.len());
    for (idx, id) in ids.into_iter().enumerate() {
        let feedback = feedbacks.get_mut(idx).unwrap();
        feedback.id = Some(id);
    }
}

pub fn feedback_updates(db: Db, feedbacks: &mut Vec<&mut ImFeedback>) {
    if feedbacks.is_empty() {
        return;
    }
    let sql = "update im_feedback set result = ?, status = ?, updateTime = ? where currentUserId = ? and title = ?";
    let mut params = vec![];
    for feedback in feedbacks.iter() {
        let mut param = vec![];
        param.push(DbParamType::OptionStr(feedback.result.as_ref()));
        param.push(DbParamType::Byte(feedback.status.clone() as i8));
        param.push(DbParamType::Str(&*feedback.user_id));
        param.push(DbParamType::DateTime2(&feedback.update_time));
        param.push(DbParamType::Str(&*feedback.title));
        params.push(param);
    }
    log::info!("db feedback update params: {:?}", params);
    db.batch_exec("feedback update", sql.to_string(), params);
}

pub fn query_feedback_by_title(db: Db, user_id: &str, title: &str) -> Option<ImFeedback> {
    let sql = format!("select {} from im_feedback where currentUserId = ? and title = ?", SELECT_COLUMNS);
    let mut params = vec![];
    params.push(DbParamType::Str(user_id));
    params.push(DbParamType::Str(title));
    db.query_one("feedback query", sql, params, Box::new(feedback_wrap))
}

pub fn query_feedbacks(db: Db, _user_id: &str, page_size: usize) -> Option<ImFeedback> {
    let sql = format!("select {} from im_feedback order by updateTime desc limit 0, {}", SELECT_COLUMNS, page_size);
    let params = vec![];
    db.query_one("feedback query", sql.to_string(), params, Box::new(feedback_wrap))
}

pub fn feedback_total(db: Db)-> usize {
    let size = db.count("feedback total", c"select count(*) from im_feedback", Vec::new());
    log::info!("db feedback count: {}", size);
    size
}



fn feedback_wrap(stmt: *mut sqlite3_stmt) -> ImFeedback {
    unsafe {
        let mut adder = Adder::new();
        let id = db_get_int64(stmt, adder.add());
        let user_id = db_get_string(stmt, adder.add()).unwrap();
        let server_id = db_get_string(stmt, adder.add());
        let title = db_get_string(stmt, adder.add()).unwrap();
        let content = db_get_string(stmt, adder.add()).unwrap();
        let result = db_get_string(stmt, adder.add());
        let status = db_get_enum(stmt, adder.add());
        let create_time = db_get_time(stmt, adder.add());
        let update_time = db_get_time(stmt, adder.add());

        ImFeedback {
            id: Some(id),
            user_id,
            server_id,
            title,
            content,
            result,
            status,
            create_time,
            update_time,
        }
    }
}